home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / dev / lang / SmallEiffel.lha / SmallEiffel / lib_se / run_class.e < prev    next >
Text File  |  1998-12-22  |  43KB  |  1,873 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  4. --                       http://www.loria.fr/SmallEiffel
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it 
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later 
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License 
  11. -- for  more  details.  You  should  have  received a copy of the GNU General 
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class RUN_CLASS
  17.    --
  18.    -- Only for class with objects at execution time.
  19.    --
  20.    
  21. inherit GLOBALS;
  22.    
  23. creation {SMALL_EIFFEL} make
  24.    
  25. feature
  26.    
  27.    current_type: TYPE;
  28.      -- Runnable corresponding one.
  29.    
  30.    id: INTEGER;
  31.      -- Id of the receiver to produce C code. 
  32.    
  33.    at_run_time: BOOLEAN;
  34.      -- True if `current_type' is really created (only when 
  35.      -- direct instances of `current_type' exists at run time).
  36.    
  37.    running: ARRAY[RUN_CLASS];
  38.      -- Void or the set of all `at_run_time' directly compatible 
  39.      -- run classes. A run class is directly compatible with one
  40.      -- another only when it can be directly substitute with 
  41.      -- current run class.
  42.      -- Thus, if current run class is reference, `running' are all 
  43.      -- reference run classes. If current run class is expanded, 
  44.      -- `running' has only one element (the current class itself).
  45.    
  46.    class_invariant: CLASS_INVARIANT;
  47.      -- Collected Runnable invariant if any.
  48.  
  49.    compile_to_c_done: BOOLEAN;
  50.          -- True if `compile_to_c' has already be called.
  51.  
  52. feature {RUN_CLASS}
  53.    
  54.    feature_dictionary: DICTIONARY[RUN_FEATURE,STRING];
  55.      -- Access to the runnable version of a feature.
  56.      -- To avoid clash between infix and prefix names, 
  57.      -- `to_key' of class NAME is used as entry.
  58.    
  59. feature {NONE}
  60.  
  61.    tagged_mem: INTEGER;
  62.      -- 0 when not computed, 1 when tagged or -1
  63.  
  64. feature {NONE}
  65.    
  66.    make(t: like current_type) is
  67.       require
  68.      t.run_type = t
  69.       local
  70.      run_string: STRING;
  71.      rcd: DICTIONARY[RUN_CLASS,STRING];
  72.      rc: RUN_CLASS;
  73.      i: INTEGER;
  74.       do
  75.      compile_to_c_done := true;
  76.      current_type := t;
  77.      !!actuals_clients.with_capacity(16);
  78.      run_string := t.run_time_mark;
  79.      id := id_provider.item(run_string);
  80.      check
  81.         not small_eiffel.run_class_dictionary.has(run_string);
  82.      end;
  83.      small_eiffel.run_class_dictionary.put(Current,run_string);
  84.      !!feature_dictionary.make;
  85.      small_eiffel.incr_magic_count;
  86.      if t.is_expanded then
  87.         set_at_run_time;
  88.         t.base_class.check_expanded_with(t);
  89.      else
  90.         from
  91.            rcd := small_eiffel.run_class_dictionary;
  92.            i := 1;
  93.         until
  94.            i > rcd.count
  95.         loop
  96.            rc := rcd.item(i);
  97.            if rc.at_run_time and then 
  98.           rc.current_type.is_reference and then
  99.           rc.is_running_of(Current)
  100.         then
  101.           add_running(rc);
  102.            end;
  103.            i := i + 1;
  104.         end;
  105.      end;
  106.       ensure
  107.      current_type = t
  108.       end;
  109.  
  110. feature
  111.  
  112.    is_tagged: BOOLEAN is
  113.       require
  114.      small_eiffel.is_ready
  115.       do
  116.      if tagged_mem = 0 then
  117.         if current_type.is_expanded then
  118.            tagged_mem := -1;
  119.         elseif at_run_time then 
  120.            if run_control.boost then
  121.           if small_eiffel.is_tagged(Current) then
  122.              tagged_mem := 1;
  123.           else
  124.              tagged_mem := -1;
  125.           end;
  126.            else
  127.           tagged_mem := 1;
  128.            end;
  129.         end;
  130.      end;
  131.      Result := tagged_mem = 1;
  132.       ensure
  133.      tagged_mem /= 0
  134.       end;
  135.    
  136.    is_expanded: BOOLEAN is
  137.       do
  138.      Result := current_type.is_expanded;
  139.       end;
  140.    
  141.    writable_attributes: ARRAY[RUN_FEATURE_2] is
  142.      -- Computed and ordered array of writable attributes.
  143.      -- Storage in C struct is to be done in reverse 
  144.      -- order (from `upper' to `lower').
  145.      -- Order is done according to the level of attribute 
  146.      -- definition in the inheritance graph to allow more 
  147.      -- stupid switch to be removed.
  148.       require
  149.      small_eiffel.is_ready;
  150.      at_run_time
  151.       local
  152.      rf2: RUN_FEATURE_2;
  153.      i: INTEGER;
  154.       do
  155.      if writable_attributes_mem = Void then
  156.         from
  157.            i := 1;
  158.         until
  159.            i > feature_dictionary.count
  160.         loop
  161.            rf2 ?= feature_dictionary.item(i);
  162.            if rf2 /= Void then
  163.           if writable_attributes_mem = Void then
  164.              writable_attributes_mem := <<rf2>>;
  165.           else
  166.              writable_attributes_mem.add_last(rf2);
  167.           end;
  168.            end;
  169.            i := i + 1;
  170.         end;
  171.         if writable_attributes_mem /= Void then
  172.            sort_wam(writable_attributes_mem);
  173.         end;
  174.      end;
  175.      Result := writable_attributes_mem;
  176.       ensure
  177.      Result /= Void implies Result.lower = 1
  178.       end;
  179.  
  180. feature -- For implicit conversion from expanded to reference :
  181.  
  182.    used_as_reference is
  183.       require
  184.      current_type.is_expanded;
  185.      not current_type.is_basic_eiffel_expanded
  186.       local
  187.      rtm: STRING;
  188.      type_ref_to_exp: TYPE_REF_TO_EXP;
  189.       do
  190.      rtm := current_type.run_time_mark;
  191.      if not to_reference_memory.has(rtm) then
  192.         !!type_ref_to_exp.make(current_type);
  193.         to_reference_memory.put(type_ref_to_exp,rtm);
  194.      end;
  195.       end;
  196.  
  197.    to_reference: TYPE is
  198.       do
  199.      Result := to_reference_memory.at(current_type.run_time_mark);
  200.       end;
  201.  
  202. feature {TYPE}
  203.  
  204.    jvm_to_reference is
  205.      -- Produce code to convert the pushed expanded into the 
  206.      -- corresponding TYPE_REF_TO_EXP type.
  207.       require
  208.      current_type.is_expanded
  209.       local 
  210.      ref_type: TYPE;
  211.       do
  212.      ref_type := to_reference;
  213.      ref_type.run_class.jvm_reference_from(current_type);
  214.       end;
  215.  
  216. feature {RUN_CLASS}
  217.  
  218.    jvm_reference_from(exp_type: TYPE) is
  219.       require
  220.      exp_type.is_expanded
  221.       local
  222.      idx: INTEGER;
  223.      ca: like code_attribute;
  224.      cp: like constant_pool;
  225.       do
  226.      ca := code_attribute;
  227.      cp := constant_pool;
  228.      idx := jvm_constant_pool_index;
  229.      ca.opcode_new(idx);
  230.      ca.opcode_dup;
  231.            idx := cp.idx_methodref1(idx,fz_35,fz_29);
  232.      ca.opcode_invokespecial(idx,-1);
  233.      ca.opcode_dup_x1;
  234.      ca.opcode_swap;
  235.      tmp_string.clear;
  236.      exp_type.jvm_descriptor_in(tmp_string);
  237.      idx := cp.idx_fieldref3(fully_qualified_name,us_item,tmp_string);
  238.      ca.opcode_putfield(idx,-2);
  239.       end;
  240.  
  241. feature {NONE}
  242.    
  243.    to_reference_memory: DICTIONARY[TYPE_REF_TO_EXP,STRING] is
  244.       once
  245.      !!Result.make;
  246.       end;
  247.    
  248. feature {CALL_PROC_CALL}
  249.    
  250.    get_rf(target: EXPRESSION; fn1: FEATURE_NAME; ct: TYPE): RUN_FEATURE is
  251.      -- Compute or simply fetch the corresponding RUN_FEATURE for
  252.      -- `target' and `fn1' in context `ct' (the type of Current).
  253.      -- Exporting rules are automatically checked and possible
  254.      -- rename are also done using `start_position' of `fn1'.
  255.      -- No return when an error occurs because `fatal_error' is called.
  256.       local
  257.      is_current: BOOLEAN;
  258.      fn2: FEATURE_NAME;
  259.      wbc, wbc2: BASE_CLASS;
  260.      target_type, constraint: TYPE;
  261.      tfg: TYPE_FORMAL_GENERIC;
  262.      bcn: CLASS_NAME;
  263.       do
  264.      target_type := target.result_type;
  265.      is_current := target.is_current;
  266.      wbc := fn1.start_position.base_class;
  267.      if is_current or else target_type.is_like_current then
  268.         fn2 := target_type.base_class.new_name_of(wbc,fn1);
  269.         if fn2 /= fn1 then
  270.            eh.add_position(fn1.start_position);
  271.            Result := get_or_fatal_error(fn2);
  272.            eh.cancel;
  273.         else
  274.            Result := get_or_fatal_error(fn1);
  275.         end;
  276.      elseif target_type.is_formal_generic then
  277.         tfg ?= target_type;
  278.         check
  279.            tfg /= Void
  280.         end;
  281.         constraint := tfg.constraint;
  282.         if constraint = Void then
  283.            Result := get_or_fatal_error(fn1);
  284.         elseif not tfg.is_a(constraint) then
  285.            eh.print_as_error;
  286.            eh.add_position(fn1.start_position);
  287.            fatal_error("Constraint genericity violation.");
  288.         else
  289.            wbc2 := constraint.start_position.base_class;
  290.            if wbc2 = wbc or else wbc.is_subclass_of(wbc2) then
  291.           fn2 := tfg.base_class.new_name_of(constraint.base_class,fn1);
  292.           Result := get_or_fatal_error(fn2);
  293.            else
  294.           Result := get_or_fatal_error(fn1);
  295.            end;
  296.         end;
  297.      else
  298.         Result := get_or_fatal_error(fn1);
  299.      end;
  300.      Result.add_client(Current);
  301.      if nb_errors = 0 and then not is_current then
  302.         bcn := ct.base_class.name;
  303.         if not Result.is_exported_in(bcn) then
  304.            eh.add_position(Result.start_position);
  305.            eh.append(" Cannot use feature %"");
  306.            eh.append(fn1.to_string);
  307.            error(fn1.start_position,"%" here.");
  308.            eh.add_position(fn1.start_position);
  309.            eh.append("Forbidden call when type of Current is ");
  310.            eh.append(ct.run_time_mark);
  311.            fatal_error(fz_dot);
  312.         end;
  313.      end;
  314.       ensure
  315.      Result /= Void
  316.       end;
  317.  
  318. feature {TYPE_LIKE_FEATURE}
  319.  
  320.    get_result_type(fn: FEATURE_NAME): TYPE is
  321.      -- Computes only the result type of `fn' when this feature
  322.      -- is not yet runnable.
  323.      -- Possible rename is also done using the `start_position' of
  324.      -- `fn'. No return when an error occurs because `fatal_error' 
  325.      -- is called.
  326.       require
  327.      not small_eiffel.is_ready
  328.       local
  329.      fn2: FEATURE_NAME;
  330.      wbc: BASE_CLASS;
  331.      rf: RUN_FEATURE;
  332.      fn2_key: STRING;
  333.      f: E_FEATURE;
  334.      bc: BASE_CLASS;
  335.       do
  336.      wbc := fn.start_position.base_class;
  337.      fn2 := base_class.new_name_of(wbc,fn);
  338.      fn2_key := fn2.to_key;
  339.      if feature_dictionary.has(fn2_key) then
  340.         rf := feature_dictionary.at(fn2_key);
  341.         Result := rf.result_type;
  342.         if Result.is_run_type then
  343.            Result := Result.run_type;
  344.         else
  345.            Result := Result.to_runnable(current_type);
  346.            Result := Result.run_type;
  347.         end;
  348.      else
  349.         bc := base_class;
  350.         f := bc.look_up_for(Current,fn2);
  351.         if f = Void then
  352.            efnf(bc,fn2);
  353.            eh.add_position(fn.start_position);
  354.            eh.add_position(fn2.start_position);
  355.            fatal_error(" Anchor not found.");
  356.         else
  357.            Result := f.result_type;
  358.            if Result = Void  then
  359.           eh.add_position(f.start_position);
  360.           eh.add_position(fn.start_position);
  361.           eh.add_position(fn2.start_position);
  362.           fatal_error(" Anchor found is a procedure.");
  363.            else
  364.           Result := Result.to_runnable(current_type);
  365.           Result := Result.run_type;
  366.            end;
  367.         end;
  368.      end;
  369.       ensure
  370.      Result = Result.run_type
  371.       end;
  372.  
  373. feature
  374.  
  375.    get_rf_with(fn: FEATURE_NAME): RUN_FEATURE is
  376.      -- Compute or simply fetch the corresponding RUN_FEATURE.
  377.      -- Possible rename are also done using `start_position' of
  378.      -- `fn'. No return when an error occurs because `fatal_error'
  379.      -- is called.
  380.       require
  381.      base_class = fn.start_position.base_class or else
  382.      base_class.is_subclass_of(fn.start_position.base_class)
  383.       local
  384.      fn2: FEATURE_NAME;
  385.      wbc: BASE_CLASS;
  386.       do
  387.      wbc := fn.start_position.base_class;
  388.      fn2 := base_class.new_name_of(wbc,fn);
  389.      if fn2 /= fn then
  390.         eh.add_position(fn.start_position);
  391.         Result := get_or_fatal_error(fn2);
  392.         eh.cancel;
  393.      else
  394.         Result := get_or_fatal_error(fn2);
  395.      end;
  396.       ensure
  397.      Result /= Void
  398.       end;
  399.  
  400.    dynamic(up_rf: RUN_FEATURE): RUN_FEATURE is
  401.      -- Assume the current type of `up_rf' is a kind of 
  402.      -- `current_type'. The result is the concrete one
  403.      -- according to dynamic dispatch rules.
  404.       require
  405.      up_rf /= Void;
  406.      is_running_of(up_rf.run_class)
  407.       local
  408.      fn, up_fn: FEATURE_NAME;
  409.      up_type: TYPE;
  410.       do
  411.      up_type := up_rf.current_type;
  412.      if Current = up_type.run_class then
  413.         Result := up_rf;
  414.      else
  415.         up_fn := up_rf.name;
  416.         fn := base_class.new_name_of(up_type.base_class,up_fn);
  417.         Result := get_or_fatal_error(fn);
  418.      end;
  419.       ensure
  420.      Result /= Void;
  421.      Result.run_class = Current;
  422.       end;
  423.  
  424. feature
  425.    
  426.    base_class: BASE_CLASS is
  427.      -- Corresponding base class.
  428.       do
  429.      Result := current_type.base_class;
  430.       ensure
  431.      Result /= Void
  432.       end;
  433.    
  434.    base_class_name: CLASS_NAME is
  435.      -- Corresponding base class name.
  436.       do
  437.      Result := current_type.base_class_name;
  438.       ensure
  439.      Result /= Void
  440.       end;
  441.  
  442. feature 
  443.    
  444.    set_at_run_time is
  445.      -- Set Current `at_run_time' and do needed update of others 
  446.      -- instances of RUN_CLASS.
  447.       require
  448.      not base_class.is_deferred
  449.       local
  450.      rcd: DICTIONARY[RUN_CLASS,STRING];
  451.      rc: RUN_CLASS;
  452.      i: INTEGER;
  453.       do
  454.      if not at_run_time  then
  455.         check
  456.            not small_eiffel.is_ready
  457.         end;
  458.         at_run_time := true;
  459.         compile_to_c_done := false;
  460.         runnable_class_invariant_done := false;
  461.         add_running(Current);
  462.         small_eiffel.incr_magic_count;
  463.         if current_type.is_reference then
  464.            from
  465.           rcd := small_eiffel.run_class_dictionary;
  466.           i := 1;
  467.            until
  468.           i > rcd.count
  469.            loop
  470.           rc := rcd.item(i);
  471.           if Current.is_running_of(rc) then
  472.              rc.add_running(Current);
  473.           end;
  474.           i := i + 1;
  475.            end;
  476.         end;
  477.      end;
  478.       ensure
  479.      at_run_time;
  480.      running.has(Current)
  481.       end;
  482.    
  483. feature {TYPE}
  484.  
  485.    gc_mark_to_follow: BOOLEAN is
  486.       -- *** TO REMOVE ***
  487.       local
  488.      i: INTEGER;
  489.      r: like running;
  490.      rc: like Current;
  491.       do
  492.      r := running;
  493.      if r /= Void then
  494.         from
  495.            i := r.upper;
  496.         until
  497.            Result or else i = 0
  498.         loop
  499.            rc := r.item(i);
  500.            if rc = Current then
  501.           Result := need_gc_mark;
  502.            else
  503.           Result := rc.current_type.need_gc_mark_function;
  504.            end;
  505.            i := i - 1;
  506.         end;
  507.      end;
  508.       end;
  509.  
  510. feature {TYPE}
  511.  
  512.    c_print_function is
  513.       require
  514.      run_control.no_check
  515.       local
  516.      body: STRING;
  517.      ct, t: TYPE;
  518.      i: INTEGER;
  519.      wa: like writable_attributes;
  520.      rf2: RUN_FEATURE_2;
  521.       do
  522.      body := "... (to change ;-)";
  523.      ct := current_type;
  524.      tmp_string.copy("void se_prinT");
  525.      id.append_in(tmp_string);
  526.      tmp_string.append("(T");
  527.      id.append_in(tmp_string);
  528.      if ct.is_reference then
  529.         tmp_string.extend('*');
  530.      end;
  531.      tmp_string.append("*o)");
  532.      body.clear;
  533.      if ct.is_reference then
  534.         body.append("if(*o==NULL){%N%
  535.             %fprintf(SE_ERR,%"Void%");%N%
  536.             %return;%N}%N");
  537.      end;
  538.      body.append("fprintf(SE_ERR,%"");
  539.      body.append(ct.run_time_mark);
  540.      body.append("%");%N");
  541.      if ct.is_reference or else ct.is_native_array then 
  542.         body.append("fprintf(SE_ERR,%"#%%p%",*o);%N");
  543.      end;
  544.      wa := writable_attributes;
  545.      if wa /= Void then
  546.         body.append("fprintf(SE_ERR,%"\n\t[ %");%N");
  547.         from
  548.            i := wa.upper;
  549.         until
  550.            i = 0
  551.         loop
  552.            rf2 := wa.item(i);
  553.            t := rf2.result_type;
  554.            body.append("fprintf(SE_ERR,%"");
  555.            body.append(rf2.name.to_string);
  556.            body.append(" = %");%Nse_prinT");
  557.            if t.is_expanded then
  558.           t.id.append_in(body);
  559.            elseif t.is_string then
  560.           body.extend('7');
  561.            else
  562.           body.extend('0');
  563.            end;
  564.            body.append("((void*)(&((*o)");
  565.            if ct.is_reference then
  566.           body.append("->");
  567.            else
  568.           body.extend('.');
  569.            end;
  570.            body.extend('_');
  571.            body.append(rf2.name.to_string);
  572.            body.append(")));%N");
  573.            i := i - 1;
  574.            if i > 0 then
  575.           body.append("fprintf(SE_ERR,%"\n\t  %");%N");
  576.            end;
  577.         end;
  578.         body.append("fprintf(SE_ERR,%"\n\t]%");%N");
  579.      end;
  580.      cpp.put_c_function(tmp_string,body);
  581.       end;
  582.  
  583.    c_object_model_in(str: STRING) is
  584.       local
  585.      wa: like writable_attributes;
  586.      i: INTEGER;
  587.      rf2: RUN_FEATURE_2;
  588.      t: TYPE;
  589.       do
  590.      wa := writable_attributes;
  591.      if wa = Void then
  592.         if is_tagged then
  593.            str.extend('{');
  594.            id.append_in(str);
  595.            str.extend('}');
  596.         else
  597.            current_type.c_initialize_in(str);
  598.         end;
  599.      else
  600.         str.extend('{');
  601.         if is_tagged then
  602.            id.append_in(str);
  603.            str.extend(',');
  604.         end;
  605.         from
  606.            i := wa.upper;
  607.         until
  608.            i = 0
  609.         loop
  610.            rf2 := wa.item(i);
  611.            t := rf2.result_type;
  612.            t.c_initialize_in(str);
  613.            i := i - 1;
  614.            if i > 0 then
  615.           str.extend(',');
  616.            end;
  617.         end;
  618.         str.extend('}');
  619.      end;
  620.       end;
  621.  
  622. feature {SMALL_EIFFEL}
  623.    
  624.    falling_down is
  625.       -- Falling down of Current `feature_dictionary' in `running'.
  626.       local
  627.      rf: RUN_FEATURE;
  628.      i: INTEGER;
  629.       do
  630.      from
  631.         i := 1;
  632.      until
  633.         i > feature_dictionary.count
  634.      loop
  635.         rf := feature_dictionary.item(i);
  636.         rf.fall_down;
  637.         i := i + 1;
  638.      end;
  639.      prepare_strip;
  640.       end;
  641.  
  642.    afd_check is
  643.      -- After Falling Down Check.
  644.       local
  645.      rf: RUN_FEATURE;
  646.      i: INTEGER;
  647.      rc: like Current;
  648.      rt: TYPE;
  649.       do
  650.      runnable_class_invariant;
  651.      from
  652.         i := 1;
  653.      until
  654.         i > feature_dictionary.count
  655.      loop
  656.         rf := feature_dictionary.item(i);
  657.         rf.afd_check;
  658.         rt := rf.result_type;
  659.         if rt /= Void then
  660.            if rt.is_none then
  661.            else 
  662.           rc := rt.run_class;
  663.            end;
  664.         end;
  665.         i := i + 1;
  666.      end;
  667.      if class_invariant /= Void then
  668.         class_invariant.afd_check;
  669.      end;
  670.       end;
  671.  
  672. feature {NONE}
  673.  
  674.    runnable_class_invariant_done: BOOLEAN;
  675.  
  676.    runnable_class_invariant is
  677.       local
  678.      r: like runnable;
  679.       do
  680.      if not runnable_class_invariant_done then
  681.         runnable_class_invariant_done := true;
  682.         if run_control.invariant_check then
  683.            if at_run_time then
  684.           ci_collector.clear;
  685.           base_class.collect_invariant(Current);
  686.           r := runnable(ci_collector,current_type,Void);
  687.           if r /= Void then
  688.              small_eiffel.incr_magic_count;
  689.              !!class_invariant.make_runnable(r,current_type,Void); 
  690.           end;
  691.            end;
  692.         end;
  693.      end;
  694.       end;
  695.    
  696. feature {NONE}
  697.  
  698.    c_header_pass_level_done: INTEGER;
  699.  
  700. feature
  701.  
  702.    c_header_pass1 is
  703.       require
  704.      cpp.on_h
  705.       do
  706.      if at_run_time then
  707.         if c_header_pass_level_done < 1 then
  708.            current_type.c_header_pass1;
  709.            c_header_pass_level_done := 1;
  710.         end;
  711.      end;
  712.       ensure
  713.      cpp.on_h
  714.       end;
  715.    
  716.    c_header_pass2 is
  717.       require
  718.      cpp.on_h
  719.       do
  720.      if at_run_time then
  721.         if c_header_pass_level_done < 2 then
  722.            current_type.c_header_pass2;
  723.            c_header_pass_level_done := 2;
  724.         end;
  725.      end;
  726.       ensure
  727.      cpp.on_h
  728.       end;
  729.    
  730.    c_header_pass3 is
  731.       require
  732.      cpp.on_h
  733.       local
  734.      i: INTEGER;
  735.      attribute_type: TYPE;
  736.       do
  737.      if at_run_time then
  738.         if c_header_pass_level_done < 3 then
  739.            if current_type.is_user_expanded and then 
  740.           writable_attributes /= Void 
  741.         then
  742.           from
  743.              i := writable_attributes.upper;
  744.           until
  745.              i = 0
  746.           loop
  747.              attribute_type := writable_attributes.item(i).result_type;
  748.              if attribute_type.is_expanded then
  749.             attribute_type.run_class.c_header_pass3;
  750.              end;
  751.              i := i - 1;
  752.           end;
  753.            end;
  754.            current_type.c_header_pass3;
  755.            c_header_pass_level_done := 3;
  756.         end;
  757.      end;
  758.       ensure
  759.      cpp.on_h
  760.       end;
  761.    
  762.    c_header_pass4 is
  763.       require
  764.      cpp.on_h
  765.       do
  766.      if at_run_time then
  767.         if c_header_pass_level_done < 4 then
  768.            current_type.c_header_pass4;
  769.            c_header_pass_level_done := 4;
  770.         end;
  771.      end;
  772.       ensure
  773.      cpp.on_h
  774.       end;
  775.    
  776. feature {GC_HANDLER}
  777.  
  778.    gc_define1 is
  779.       require
  780.      not gc_handler.is_off
  781.       do
  782.      if at_run_time then
  783.         current_type.gc_define1;
  784.      end;
  785.       end;
  786.    
  787.    gc_define2 is
  788.       require
  789.      not gc_handler.is_off
  790.       do
  791.      if at_run_time then
  792.         current_type.gc_define2;
  793.      end;
  794.       end;
  795.    
  796.    gc_info_in(str: STRING) is
  797.      -- Produce C code to print GC information.
  798.       require
  799.      not gc_handler.is_off;
  800.      gc_handler.info_flag
  801.       do
  802.      if at_run_time then
  803.         current_type.gc_info_in(str);
  804.      end;
  805.       end;
  806.  
  807.    just_before_gc_mark_in(body: STRING) is
  808.       require
  809.      not gc_handler.is_off
  810.       do
  811.      if at_run_time then
  812.         current_type.just_before_gc_mark_in(body);
  813.      end;
  814.       end;
  815.  
  816.    gc_initialize is
  817.      -- Produce code to initialize GC in the main C function.
  818.       require
  819.      not gc_handler.is_off
  820.       do
  821.      if at_run_time then
  822.         current_type.gc_initialize;
  823.      end;
  824.       end;
  825.  
  826. feature {TYPE}
  827.  
  828.    gc_mark_fixed_size(is_unmarked: BOOLEAN; body: STRING) is
  829.      -- The main purpose is to compute for example the best
  830.      -- body for the gc_markXXX function. In fact, this
  831.      -- feature may be called to produce C code when C variable
  832.      -- `o' is not NULL and when `o' is of some concrete type 
  833.      -- (Tid*) where `id' is the one of the current RUN_CLASS.
  834.      -- Finally, when `is_unmarked' is true, object `o' is unmarked. 
  835.       require
  836.      not gc_handler.is_off;
  837.      not current_type.is_native_array;
  838.      at_run_time
  839.       local
  840.      rf2: RUN_FEATURE_2;
  841.      t: TYPE;
  842.      rc: RUN_CLASS;
  843.      i: INTEGER;
  844.       do
  845.      wa_buf.clear;
  846.      wa_cyclic_buf.clear;
  847.      if writable_attributes /= Void then
  848.         from
  849.            i := writable_attributes.upper;
  850.         until
  851.            i = 0
  852.         loop
  853.            rf2 := writable_attributes.item(i);
  854.            t := rf2.result_type;
  855.            if t.need_gc_mark_function then
  856.           rc :=  t.run_class;
  857.           wa_cycle.clear;
  858.           wa_cycle.add_last(rf2);
  859.           if rc.is_wa_cycle(Current) then
  860.              wa_cyclic_buf.add_last(rf2);
  861.           else
  862.              wa_buf.add_last(rf2);
  863.           end;
  864.            end;
  865.            i := i - 1;
  866.         end;
  867.      end;
  868.      if wa_buf.empty and then wa_cyclic_buf.empty then
  869.         gc_set_fsoh_marked_in(body);
  870.      else
  871.         if wa_cyclic_buf.upper >= 0 then
  872.            body.append("begin:%N");
  873.         end;
  874.         if not is_unmarked then
  875.            body.append(
  876.                   "if(((gc");
  877.            id.append_in(body);
  878.            body.append(
  879.                   "*)o)->header.flag==FSOH_UNMARKED){%N");
  880.         end;
  881.         gc_set_fsoh_marked_in(body);
  882.         from -- Ordinary attributes :
  883.            i := wa_buf.upper;
  884.         until
  885.            i < 0
  886.         loop
  887.            rf2 := wa_buf.item(i);
  888.            mark_attribute(body,rf2);
  889.            i := i - 1;
  890.         end;
  891.         from -- Cyclic attributes :
  892.            i := wa_cyclic_buf.upper;
  893.         until
  894.            i < 0
  895.         loop
  896.            rf2 := wa_cyclic_buf.item(i);
  897.            t := rf2.result_type;
  898.            rc :=  t.run_class;
  899.            wa_cycle.clear;
  900.            wa_cycle.add_last(rf2);
  901.            if rc.is_wa_cycle(Current) then
  902.            end;
  903.            if i = 0 and then 
  904.           wa_cycle.count = 1 and then
  905.           rc.running /= Void and then
  906.           rc.running.count = 1 and then
  907.           rc.running.first = Current
  908.         then
  909.           body.append("o=(void*)o->_");
  910.           body.append(rf2.name.to_string);
  911.           body.append(";%Nif((o!=NULL)");
  912.           if is_unmarked then
  913.              body.append("&&(((gc");
  914.              id.append_in(body);
  915.              body.append(
  916.                         "*)o)->header.flag==FSOH_UNMARKED))");
  917.           else 
  918.              body.extend(')');
  919.           end;
  920.           body.append("goto begin;%N");
  921.            else
  922.           mark_attribute(body,rf2);
  923.            end;
  924.            i := i - 1;
  925.         end;
  926.         if not is_unmarked then
  927.            body.extend('}');
  928.         end;
  929.      end;
  930.       end;
  931.    
  932. feature {TYPE}
  933.  
  934.    gc_align_mark_fixed_size(body: STRING) is
  935.      -- Compute the best body for gc_align_markXXX of 
  936.      -- a fixed_size object.
  937.       require
  938.      not gc_handler.is_off;
  939.      not current_type.is_native_array;
  940.      at_run_time
  941.       do
  942.      body.append("gc");
  943.      id.append_in(body);
  944.      body.append(
  945.             "*b=(void*)&(c->first_object);%N%
  946.         %if(c->header.state_type==FSO_STORE_CHUNK){%N%
  947.         %if(p>=store");
  948.      id.append_in(body);
  949.      body.append(
  950.         ")return;}%N%
  951.         %else{%N%
  952.         %if(p>(b+(c->count_minus_one)))return;}%N%
  953.         %if(p<b)return;%N%
  954.         %if(((((char*)p)-((char*)b))%%sizeof(*b))==0){%N%
  955.         %if(p->header.flag==FSOH_UNMARKED){%N%
  956.         %T");
  957.      id.append_in(body);
  958.      body.append("*o=(void*)p;%N");
  959.      gc_mark_fixed_size(true,body);
  960.      body.append("}%N}%N");
  961.       end;
  962.  
  963. feature {RUN_CLASS}
  964.    
  965.    fill_up_with(rc: RUN_CLASS; fd: like feature_dictionary) is
  966.      -- Fill up `feature_dictionary' with all features coming from
  967.      -- `rc' X `fd'.
  968.       require
  969.      rc /= Current;
  970.      is_running_of(rc);
  971.      fd /= Void;
  972.       local
  973.      bc1, bc2: BASE_CLASS;
  974.      fn1, fn2: FEATURE_NAME;
  975.      rf: RUN_FEATURE;
  976.      i: INTEGER;
  977.       do
  978.      from
  979.         i := 1;
  980.         bc1 := rc.base_class;
  981.         bc2 := base_class;
  982.      until
  983.         i > fd.count
  984.      loop
  985.         rf := fd.item(i);
  986.         if rf.fall_in(Current) then
  987.            fn1 := rf.name;
  988.            fn2 := bc2.name_of(bc1,fn1);
  989.            rf := get_feature(fn2);
  990.         end;
  991.         i := i + 1;
  992.      end;
  993.       end;
  994.    
  995.    add_running(rc: RUN_CLASS) is
  996.       require
  997.      rc /= Void;
  998.       do
  999.      if running = Void then
  1000.         running := <<rc>>;
  1001.      else
  1002.         if not running.fast_has(rc) then
  1003.            running.add_last(rc);
  1004.         end;
  1005.      end;
  1006.       end;
  1007.    
  1008. feature {RUN_CLASS}
  1009.  
  1010.    is_running_of(other: like Current): BOOLEAN is
  1011.      -- Can the Current RUN_CLASS be used in place of `other'.
  1012.       require
  1013.      other /= Void
  1014.       local
  1015.      t1, t2: TYPE;
  1016.       do
  1017.      if other = Current then
  1018.         Result := true;
  1019.      else
  1020.         t1 := current_type;
  1021.         t2 := other.current_type;
  1022.         if t1.is_basic_eiffel_expanded and then 
  1023.            t2.is_basic_eiffel_expanded then
  1024.         else
  1025.            Result := t1.is_a(t2);
  1026.            if not Result then
  1027.           eh.cancel;
  1028.            end;
  1029.         end;
  1030.      end;
  1031.       ensure
  1032.      nb_errors = old nb_errors
  1033.       end;
  1034.    
  1035. feature {E_FEATURE}
  1036.    
  1037.    at(fn: FEATURE_NAME): RUN_FEATURE is
  1038.      -- Simple look in the dictionary to see if the feature
  1039.      -- is already computed.
  1040.       require
  1041.      fn /= Void;
  1042.       local
  1043.      to_key: STRING;
  1044.       do
  1045.      to_key := fn.to_key;
  1046.      if feature_dictionary.has(to_key) then
  1047.         Result := feature_dictionary.at(to_key);
  1048.      end;
  1049.       end;
  1050.    
  1051. feature {E_STRIP}
  1052.  
  1053.    set_strip_used is
  1054.       do
  1055.      strip_used := true;
  1056.       end;
  1057.  
  1058. feature {NONE}
  1059.  
  1060.    strip_used: BOOLEAN;
  1061.  
  1062.    prepare_strip is
  1063.       local
  1064.      rf2: RUN_FEATURE_2;
  1065.      i: INTEGER;
  1066.       do
  1067.      if strip_used then
  1068.         from
  1069.            i := 1;
  1070.         until
  1071.            i > feature_dictionary.count
  1072.         loop
  1073.            rf2 ?= feature_dictionary.item(i);
  1074.            if rf2 /= Void then
  1075.           rf2.result_type.used_as_reference;
  1076.            end;
  1077.            i := i + 1;
  1078.         end;
  1079.      end;
  1080.       end;
  1081.  
  1082. feature 
  1083.    
  1084.    get_feature_with(n: STRING): RUN_FEATURE is
  1085.      -- Assume that `n' is really the final name in 
  1086.      -- current RUN_CLASS. 
  1087.       require
  1088.      n /= Void;
  1089.       local
  1090.      sfn: SIMPLE_FEATURE_NAME;
  1091.       do
  1092.      if feature_dictionary.has(n) then
  1093.         Result := feature_dictionary.at(n);
  1094.      else
  1095.         !!sfn.make(n,Void);
  1096.         Result := get_feature(sfn);
  1097.      end;
  1098.       end;
  1099.  
  1100. feature
  1101.    
  1102.    get_copy: RUN_FEATURE is
  1103.       do
  1104.      Result := get_rf_with(class_general.get_copy.first_name);
  1105.       end;
  1106.  
  1107. feature 
  1108.  
  1109.    get_feature(fn: FEATURE_NAME): RUN_FEATURE is
  1110.      -- Assume that `fn' is really the final name in current 
  1111.      -- RUN_CLASS. Don't look for rename.
  1112.       require
  1113.      fn /= Void
  1114.       local
  1115.      f: E_FEATURE;
  1116.      fn_key: STRING;
  1117.      bc: BASE_CLASS;
  1118.       do
  1119.      fn_key := fn.to_key;
  1120.      if feature_dictionary.has(fn_key) then
  1121.         Result := feature_dictionary.at(fn_key);
  1122.      else
  1123.         check 
  1124.            not small_eiffel.is_ready;
  1125.         end;
  1126.         bc := base_class;
  1127.         f := bc.look_up_for(Current,fn);
  1128.         if f = Void then
  1129.            efnf(bc,fn);
  1130.         else
  1131.            Result := f.to_run_feature(current_type,fn);
  1132.            if Result /= Void  then
  1133.           store_feature(Result);
  1134.            else
  1135.           efnf(bc,fn);
  1136.            end;
  1137.         end;
  1138.      end;
  1139.       end;
  1140.  
  1141. feature {NONE}
  1142.  
  1143.    get_or_fatal_error(fn: FEATURE_NAME): RUN_FEATURE is
  1144.       do
  1145.      Result := get_feature(fn);
  1146.      if Result = Void then
  1147.         eh.add_position(fn.start_position);
  1148.         eh.append("Feature ");
  1149.         eh.append(fn.to_string);
  1150.         eh.append(" not found when starting look up from ");
  1151.         eh.add_type(current_type,fz_dot);
  1152.         eh.print_as_fatal_error;
  1153.      end;
  1154.       end;
  1155.    
  1156. feature {NONE}
  1157.    
  1158.    store_feature(rf: like get_feature) is
  1159.      -- To update the dictionary from outside.
  1160.      -- Note : this routine is necessary because of recursive call.
  1161.       require
  1162.      rf.run_class = Current
  1163.       local
  1164.      rf_key: STRING;
  1165.       do
  1166.      rf_key := rf.name.to_key;
  1167.      if feature_dictionary.has(rf_key) then
  1168.         check
  1169.            feature_dictionary.at(rf_key) = rf
  1170.         end;
  1171.      else
  1172.         feature_dictionary.put(rf,rf_key);
  1173.         small_eiffel.incr_magic_count;
  1174.      end;
  1175.       ensure
  1176.      get_feature(rf.name) = rf
  1177.       end;
  1178.  
  1179. feature {JVM}
  1180.  
  1181.    jvm_define_class_invariant is
  1182.      -- If needed, call the invariant for the pushed value.
  1183.       local
  1184.      ia: like class_invariant;
  1185.       do
  1186.      if run_control.invariant_check then
  1187.         ia := class_invariant;
  1188.         if ia /= Void then
  1189.            jvm.define_class_invariant_method(ia);
  1190.         end;
  1191.      end;
  1192.       end;
  1193.  
  1194. feature {JVM,TYPE} 
  1195.  
  1196.    jvm_check_class_invariant is
  1197.      -- If needed, call the invariant for the stack-top object.
  1198.      -- If invariant is correct, the same stack-top object is left
  1199.      -- on the stack.
  1200.       local
  1201.      ia: like class_invariant;
  1202.      idx: INTEGER;
  1203.      ca: like code_attribute;
  1204.      cp: like constant_pool;
  1205.       do
  1206.      if run_control.invariant_check then
  1207.         ia := class_invariant;
  1208.         if ia /= Void then
  1209.            ca := code_attribute;
  1210.            cp := constant_pool;
  1211.            ca.opcode_dup;
  1212.            opcode_checkcast;
  1213.            idx := cp.idx_methodref3(fully_qualified_name,fz_invariant,fz_29);
  1214.            ca.opcode_invokevirtual(idx,-1);
  1215.         end;
  1216.      end;
  1217.       end;
  1218.  
  1219. feature {SMALL_EIFFEL}
  1220.  
  1221.    compile_to_jvm is
  1222.       require
  1223.      at_run_time
  1224.       local
  1225.      i: INTEGER;
  1226.      rf: RUN_FEATURE;
  1227.      type_ref_to_exp: TYPE_REF_TO_EXP;
  1228.       do
  1229.      echo.put_character('%T');
  1230.      echo.put_string(current_type.run_time_mark);
  1231.      echo.put_character('%N');
  1232.      jvm.start_new_class(Current);
  1233.      from
  1234.         i := 1;
  1235.      until
  1236.         i > feature_dictionary.count
  1237.      loop
  1238.         rf := feature_dictionary.item(i);
  1239.         jvm.set_current_frame(rf);
  1240.         rf.jvm_field_or_method;
  1241.         i := i + 1;
  1242.      end;
  1243.      type_ref_to_exp ?= current_type;
  1244.      if type_ref_to_exp = Void then
  1245.         jvm.prepare_fields;
  1246.      else
  1247.         type_ref_to_exp.jvm_prepare_item_field;
  1248.      end;
  1249.      jvm.prepare_methods;
  1250.      jvm.finish_class;
  1251.       end;
  1252.  
  1253. feature {MANIFEST_ARRAY}
  1254.  
  1255.    fully_qualified_name: STRING is
  1256.       do
  1257.      if fully_qualified_name_memory = Void then
  1258.         fully_qualified_name_memory2.copy(jvm.output_name);
  1259.         fully_qualified_name_memory2.extend('/');
  1260.         fully_qualified_name_memory2.append(unqualified_name);
  1261.         !!fully_qualified_name_memory.copy(fully_qualified_name_memory2);
  1262.      end;
  1263.      Result := fully_qualified_name_memory;
  1264.       end;
  1265.  
  1266. feature {NONE} -- To speed up `fully_qualified_name' :
  1267.  
  1268.    fully_qualified_name_memory: STRING;
  1269.  
  1270.    fully_qualified_name_memory2: STRING is
  1271.       once
  1272.      !!Result.make(256);
  1273.       end;
  1274.  
  1275. feature {TYPE}
  1276.    
  1277.    jvm_type_descriptor_in(str: STRING) is
  1278.      -- Append in `str' the appropriate JVM type descriptor.
  1279.       require
  1280.      at_run_time;
  1281.      running.fast_has(Current)
  1282.       do
  1283.      check
  1284.         current_type.is_user_expanded
  1285.      end;
  1286.      str.extend('L');
  1287.      str.append(fully_qualified_name);
  1288.      str.extend(';');
  1289.       end;
  1290.  
  1291. feature {RUN_FEATURE}
  1292.  
  1293.    jvm_invoke(idx, stack_level: INTEGER) is
  1294.       local
  1295.      ct: like current_type;
  1296.       do
  1297.      ct := current_type;
  1298.      inspect
  1299.         ct.jvm_method_flags
  1300.      when 17 then
  1301.         code_attribute.opcode_invokevirtual(idx,stack_level);
  1302.      when 9 then
  1303.         code_attribute.opcode_invokestatic(idx,stack_level);
  1304.      end;
  1305.       end;
  1306.  
  1307. feature
  1308.  
  1309.    jvm_basic_new is
  1310.      -- Poduce bytecode to push a new created object with the 
  1311.      -- basic default value (the corresponding creation procedure
  1312.      -- if any is not called).
  1313.       local
  1314.      i, idx: INTEGER;
  1315.      wa: ARRAY[RUN_FEATURE_2];
  1316.      rf2: RUN_FEATURE_2;
  1317.      t2: TYPE;
  1318.      ca: like code_attribute;
  1319.      cp: like constant_pool;
  1320.       do
  1321.      ca := code_attribute;
  1322.      cp := constant_pool;
  1323.      idx := jvm_constant_pool_index;
  1324.      ca.opcode_new(idx);
  1325.      ca.opcode_dup;
  1326.            idx := cp.idx_methodref1(idx,fz_35,fz_29);
  1327.      ca.opcode_invokespecial(idx,-1);
  1328.      wa := writable_attributes;
  1329.      if wa /= Void then
  1330.         from
  1331.            i := wa.upper;
  1332.         until
  1333.            i = 0
  1334.         loop
  1335.            rf2 := wa.item(i);
  1336.            t2 := rf2.result_type.run_type;
  1337.            if t2.is_user_expanded then
  1338.           ca.opcode_dup;
  1339.           t2.run_class.jvm_expanded_push_default;
  1340.           idx := cp.idx_fieldref(rf2);
  1341.           ca.opcode_putfield(idx,-2);
  1342.            elseif t2.is_bit then
  1343.           ca.opcode_dup;
  1344.           idx := t2.jvm_push_default;
  1345.           idx := cp.idx_fieldref(rf2);
  1346.           ca.opcode_putfield(idx,-2);
  1347.            end;
  1348.            i := i - 1;
  1349.         end;
  1350.      end;
  1351.       end;
  1352.  
  1353. feature {TYPE,RUN_CLASS,NATIVE_SMALL_EIFFEL}
  1354.  
  1355.    jvm_expanded_push_default is
  1356.      -- Push the corresponding new user's expanded (either dummy 
  1357.      -- or not, initializer is automatically applied).
  1358.       require
  1359.      current_type.is_user_expanded
  1360.       local
  1361.      rf: RUN_FEATURE;
  1362.       do
  1363.      jvm_basic_new;
  1364.      rf := base_class.expanded_initializer(current_type);
  1365.      if rf /= Void then
  1366.         jvm.push_expanded_initialize(rf);
  1367.         rf.mapping_jvm;
  1368.         jvm.pop;
  1369.      end;
  1370.       end;
  1371.  
  1372. feature {JVM}
  1373.  
  1374.    unqualified_name: STRING is
  1375.      -- Also used for the corresponding file name.
  1376.       local
  1377.      ct: TYPE;
  1378.       do
  1379.      ct := current_type;
  1380.      unqualified_name_memory.copy(ct.run_time_mark);
  1381.      unqualified_name_memory.to_lower;
  1382.      unqualified_name_memory.replace_all('[','O');
  1383.      unqualified_name_memory.replace_all(']','F');
  1384.      unqualified_name_memory.replace_all(' ','_');
  1385.      unqualified_name_memory.replace_all(',','_');
  1386.      Result := unqualified_name_memory;
  1387.       end;
  1388.  
  1389. feature {NONE}
  1390.  
  1391.    unqualified_name_memory: STRING is
  1392.       once
  1393.      !!Result.make(32);
  1394.       end;
  1395.  
  1396. feature
  1397.  
  1398.    jvm_constant_pool_index: INTEGER is
  1399.      -- The fully qualified index in the constant pool.
  1400.       do
  1401.      Result := constant_pool.idx_class2(fully_qualified_name);
  1402.       end;
  1403.  
  1404. feature {SMALL_EIFFEL,TYPE}
  1405.  
  1406.    demangling is
  1407.       require
  1408.      cpp.on_h
  1409.       local
  1410.      str: STRING;
  1411.      r: like running;
  1412.      i: INTEGER;
  1413.       do
  1414.      str := "";
  1415.      str.clear;
  1416.      if at_run_time then
  1417.         str.extend('A');
  1418.         if current_type.is_reference and then not is_tagged then
  1419.            str.extend('*');
  1420.         else
  1421.            str.extend(' ');
  1422.         end;
  1423.      else
  1424.         str.extend('D');
  1425.         str.extend(' ');
  1426.      end;
  1427.      r := running;
  1428.      if r /= Void then
  1429.         r.count.append_in(str);
  1430.      end;
  1431.      from
  1432.      until
  1433.         str.count > 4
  1434.      loop
  1435.         str.extend(' ');
  1436.      end;
  1437.      str.extend('T');
  1438.      id.append_in(str);
  1439.      from
  1440.      until
  1441.         str.count > 10
  1442.      loop
  1443.         str.extend(' ');
  1444.      end;
  1445.      current_type.demangling_in(str);
  1446.      if r /= Void then
  1447.         from
  1448.            str.extend(' ');
  1449.            i := r.upper;
  1450.         until
  1451.            i = 0
  1452.         loop
  1453.            r.item(i).id.append_in(str);
  1454.            i := i - 1;
  1455.            if i > 0 then
  1456.           str.extend(',');
  1457.            end;
  1458.         end;
  1459.      end;
  1460.      str.extend('%N');
  1461.      cpp.put_string(str);
  1462.       ensure
  1463.      cpp.on_h
  1464.       end;
  1465.  
  1466. feature {SMALL_EIFFEL,RUN_CLASS}
  1467.  
  1468.    compile_to_c(deep: INTEGER) is
  1469.      -- Produce C code for features of Current. The `deep'
  1470.      -- indicator is used to sort the C output in the best order 
  1471.      -- (more C  inlinings are possible when basic functions are 
  1472.      -- produced first). As there is not always a total order 
  1473.      -- between clients, the `deep' avoid infinite track.
  1474.      -- When `deep' is greater than 0, C code writting 
  1475.          -- is produced whatever the real client relation is.
  1476.       require
  1477.      cpp.on_c;
  1478.      deep >= 0
  1479.       local
  1480.      i: INTEGER;
  1481.      rc1, rc2: like Current;
  1482.      cc1, cc2: INTEGER;
  1483.       do
  1484.      if compile_to_c_done then
  1485.      elseif not at_run_time then
  1486.         compile_to_c_done := true;
  1487.      elseif deep = 0 then
  1488.         really_compile_to_c;
  1489.      else
  1490.         i := actuals_clients.upper;
  1491.         if i >= 0 then
  1492.            from
  1493.           rc1 := Current;
  1494.           cc1 := i + 1;
  1495.            until
  1496.           i = 0
  1497.            loop
  1498.           rc2 := actuals_clients.item(i);
  1499.           if not rc2.compile_to_c_done then
  1500.              cc2 := rc2.actuals_clients.count;
  1501.              if cc2 > cc1 then
  1502.             rc1 := rc2;
  1503.             cc1 := cc2;
  1504.              end;
  1505.           end;
  1506.           i := i - 1;
  1507.            end;
  1508.            if rc1 = Current then
  1509.           really_compile_to_c;
  1510.            else
  1511.           rc1.compile_to_c(deep - 1);
  1512.            end;
  1513.         end;
  1514.      end;
  1515.       ensure
  1516.      cpp.on_c
  1517.       end;
  1518.  
  1519. feature {NONE}
  1520.  
  1521.    really_compile_to_c is
  1522.       require
  1523.      at_run_time
  1524.       local
  1525.      i: INTEGER;
  1526.      rf: RUN_FEATURE;
  1527.       do
  1528.      compile_to_c_done := true;
  1529.      cpp.split_c_start_run_class;
  1530.      echo.put_character('%T');
  1531.      echo.put_string(current_type.run_time_mark);
  1532.      echo.put_character('%N');
  1533.      from
  1534.         i := 1;
  1535.      until
  1536.         i > feature_dictionary.count
  1537.      loop
  1538.         rf := feature_dictionary.item(i);
  1539.         rf.c_define;
  1540.         i := i + 1;
  1541.      end;
  1542.      if run_control.invariant_check then
  1543.         if class_invariant /= Void then
  1544.            class_invariant.c_define;
  1545.         end;
  1546.      end;
  1547.       ensure
  1548.      compile_to_c_done
  1549.       end;
  1550.  
  1551. feature {RUN_CLASS}
  1552.  
  1553.    actuals_clients: FIXED_ARRAY[RUN_CLASS];
  1554.  
  1555. feature {RUN_FEATURE}
  1556.  
  1557.    add_client(rc: RUN_CLASS) is
  1558.       require
  1559.      rc /= Void
  1560.       local
  1561.      i: INTEGER;
  1562.       do
  1563.      i := actuals_clients.fast_index_of(rc);
  1564.      if i > actuals_clients.upper then
  1565.         actuals_clients.add_last(rc);
  1566.      end;
  1567.       end;
  1568.    
  1569. feature {BASE_CLASS}
  1570.    
  1571.    collect_invariant(ia: like class_invariant) is
  1572.       require
  1573.      ia /= Void;
  1574.       do
  1575.      ia.add_into(ci_collector);
  1576.       end;
  1577.  
  1578. feature {NONE}   
  1579.    
  1580.    writable_attributes_mem: like writable_attributes;
  1581.    
  1582.    ci_collector: ARRAY[ASSERTION] is
  1583.      -- The Class Invariant Collector.
  1584.       once
  1585.      !!Result.make(1,10);
  1586.       end;
  1587.  
  1588. feature 
  1589.  
  1590.    offset_of(rf2: RUN_FEATURE_2): INTEGER is
  1591.      -- Compute the displacement to access `rf2' in the corresponding 
  1592.      -- C struct to remove a possible stupid switch.
  1593.      -- Result is in number of bytes.
  1594.       require
  1595.      at_run_time;
  1596.      writable_attributes.fast_has(rf2);
  1597.      small_eiffel.is_ready
  1598.       local
  1599.      wa: like writable_attributes;
  1600.      t: TYPE;
  1601.      i: INTEGER;
  1602.       do
  1603.      if is_tagged then
  1604.         Result := (1).object_size;
  1605.      end;
  1606.      from
  1607.         wa := writable_attributes;
  1608.         i := wa.upper;
  1609.      invariant
  1610.         i > 0
  1611.      until
  1612.         wa.item(i) = rf2
  1613.      loop
  1614.         t := wa.item(i).result_type;
  1615.         Result := Result + t.space_for_variable;
  1616.         i := i - 1;
  1617.      end;
  1618.       end;
  1619.  
  1620. feature {NONE}
  1621.  
  1622.    sort_wam(wam: like writable_attributes) is
  1623.      -- Sort `wam' to common attribute at the end.
  1624.       require
  1625.      wam.lower = 1
  1626.       local
  1627.      min, max, buble: INTEGER;
  1628.      moved: BOOLEAN;
  1629.       do
  1630.      from  
  1631.         max := wam.upper;
  1632.         min := 1;
  1633.         moved := true;
  1634.      until
  1635.         not moved
  1636.      loop
  1637.         moved := false;
  1638.         if max - min > 0 then
  1639.            from  
  1640.           buble := min + 1;
  1641.            until
  1642.           buble > max
  1643.            loop
  1644.           if gt(wam.item(buble - 1),wam.item(buble)) then
  1645.              wam.swap(buble - 1,buble);
  1646.              moved := true;
  1647.           end;
  1648.           buble := buble + 1;
  1649.            end;
  1650.            max := max - 1;
  1651.         end;
  1652.         if moved and then max - min > 0 then
  1653.            from  
  1654.           moved := false;
  1655.           buble := max - 1;
  1656.            until
  1657.           buble < min
  1658.            loop
  1659.           if gt(wam.item(buble),wam.item(buble + 1)) then
  1660.              wam.swap(buble,buble + 1);
  1661.              moved := true;
  1662.           end;
  1663.           buble := buble - 1;
  1664.            end;
  1665.            min := min + 1;
  1666.         end;
  1667.      end;
  1668.       end;
  1669.  
  1670.    gt(rf1, rf2: RUN_FEATURE_2): BOOLEAN is
  1671.      -- True if it is better to set attribute `rf1' before
  1672.      -- attribute `rf2'.
  1673.       local
  1674.      bc1, bc2: BASE_CLASS;
  1675.      bf1, bf2: E_FEATURE;
  1676.      bcn1, bcn2: CLASS_NAME;
  1677.       do
  1678.      bf1 := rf1.base_feature;
  1679.      bf2 := rf2.base_feature;
  1680.      bc1 := bf1.base_class;
  1681.      bc2 := bf2.base_class;
  1682.      bcn1 := bc1.name;
  1683.      bcn2 := bc2.name;
  1684.      if bcn1.to_string = bcn2.to_string then
  1685.         Result := bf1.start_position.before(bf2.start_position);
  1686.      elseif bcn2.is_subclass_of(bcn1) then
  1687.         Result := true;
  1688.      elseif bcn1.is_subclass_of(bcn2) then
  1689.      elseif bc1.parent_list = Void then
  1690.         if bc2.parent_list = Void then
  1691.            Result := bcn1.to_string < bcn2.to_string;
  1692.         else
  1693.            Result := true;
  1694.         end;
  1695.      elseif bc2.parent_list = Void then
  1696.      else
  1697.         Result := bc2.parent_list.count < bc1.parent_list.count 
  1698.      end;
  1699.       end;
  1700.  
  1701. feature {NONE}
  1702.  
  1703.    efnf(bc: BASE_CLASS; fn: FEATURE_NAME) is
  1704.       require
  1705.      bc /= Void;
  1706.      fn /= Void
  1707.       do
  1708.      eh.append("Current type is ");
  1709.      eh.append(current_type.run_time_mark);
  1710.      eh.append(". There is no feature ");
  1711.      eh.append(fn.to_string);
  1712.      eh.append(" in class ");
  1713.      eh.append(bc.name.to_string);
  1714.      error(fn.start_position,fz_dot);
  1715.       end;
  1716.  
  1717. feature {NONE}
  1718.  
  1719.    tmp_string: STRING is
  1720.       once
  1721.      !!Result.make(32);
  1722.       end;
  1723.  
  1724. feature
  1725.  
  1726.    wa_buf: FIXED_ARRAY[RUN_FEATURE_2] is
  1727.       once
  1728.      !!Result.with_capacity(24);
  1729.       end;
  1730.  
  1731.    wa_cyclic_buf: FIXED_ARRAY[RUN_FEATURE_2] is
  1732.       once
  1733.      !!Result.with_capacity(24);
  1734.       end;
  1735.  
  1736. feature {RUN_CLASS}
  1737.  
  1738.    is_wa_cycle(origin: like Current): BOOLEAN is
  1739.       do
  1740.      if Current = origin then
  1741.         Result := true;
  1742.      end;
  1743.       end;
  1744.       
  1745. feature {NONE}
  1746.  
  1747.    wa_cycle: FIXED_ARRAY[RUN_FEATURE_2] is
  1748.       once
  1749.      !!Result.with_capacity(24);
  1750.       end;
  1751.    
  1752. feature {NONE}
  1753.  
  1754.    need_gc_mark: BOOLEAN is
  1755.       require
  1756.      at_run_time
  1757.       local
  1758.      i: INTEGER;
  1759.      wa: like writable_attributes;
  1760.      rf2: RUN_FEATURE_2;
  1761.      t: TYPE;
  1762.       do
  1763.      wa := writable_attributes;
  1764.      if wa /= Void then
  1765.         from
  1766.            i := wa.upper;
  1767.         until
  1768.            Result or else i = 0
  1769.         loop
  1770.            rf2 := wa.item(i);
  1771.            t := rf2.result_type;
  1772.            Result := t.need_gc_mark_function;
  1773.            i := i - 1;
  1774.         end;
  1775.      end;
  1776.       end;
  1777.  
  1778. feature {NONE}
  1779.  
  1780.    gc_set_fsoh_marked_in(body: STRING) is
  1781.       do
  1782.      if current_type.is_reference then
  1783.         body.append("((gc");
  1784.         id.append_in(body);
  1785.         body.append("*)o)->header.flag=FSOH_MARKED;%N");
  1786.      end;
  1787.       end;
  1788.  
  1789. feature {NONE}
  1790.  
  1791.    mark_attribute(body: STRING; rf2: RUN_FEATURE_2) is
  1792.       do
  1793.      tmp_string.copy("o->_");
  1794.      tmp_string.append(rf2.name.to_string);
  1795.      tmp_string.append(fz_open_c_comment);
  1796.      offset_of(rf2).append_in(tmp_string);
  1797.      tmp_string.append(fz_close_c_comment);
  1798.      gc_handler.mark_for(body,tmp_string,rf2.result_type.run_class);
  1799.       end;
  1800.  
  1801. feature {RUN_FEATURE_2}
  1802.  
  1803.    force_c_recompilation_comment(rf2: RUN_FEATURE_2) is
  1804.       require
  1805.      at_run_time;
  1806.      writable_attributes.fast_has(rf2);
  1807.      small_eiffel.is_ready
  1808.       do
  1809.      cpp.put_recompilation_comment(offset_of(rf2));
  1810.       end;
  1811.  
  1812. feature -- Some usefull JVM opcode :
  1813.  
  1814.    opcode_checkcast is
  1815.      -- May produce a `checkcast' opcode depending on 
  1816.      -- `current_type' Java byte-code mapping.
  1817.       local
  1818.      ct: TYPE;
  1819.      idx: INTEGER;
  1820.       do
  1821.      ct := current_type;
  1822.      if ct.is_basic_eiffel_expanded then
  1823.      elseif ct.is_native_array then
  1824.         tmp_string.clear;
  1825.         ct.jvm_target_descriptor_in(tmp_string);
  1826.         idx := constant_pool.idx_class2(tmp_string);
  1827.         code_attribute.opcode_checkcast(idx);
  1828.      elseif ct.is_bit then
  1829.      else
  1830.         idx := jvm_constant_pool_index;
  1831.         code_attribute.opcode_checkcast(idx);
  1832.      end;
  1833.       end;
  1834.  
  1835.    opcode_instanceof is
  1836.       require
  1837.      not current_type.is_basic_eiffel_expanded
  1838.       local
  1839.      idx: INTEGER;
  1840.       do
  1841.      idx := jvm_constant_pool_index;
  1842.      code_attribute.opcode_instanceof(idx);
  1843.       end;
  1844.  
  1845.    opcode_getfield(rf2: RUN_FEATURE_2): INTEGER is
  1846.      -- Produce a `checkcast'/`getfield' for the given
  1847.      -- attribute of the top object of the stack.
  1848.      -- stack: ... object => ... value
  1849.       local
  1850.      idx: INTEGER;
  1851.       do
  1852.      opcode_checkcast;
  1853.      idx := constant_pool.idx_fieldref(rf2);
  1854.      Result := rf2.result_type.jvm_stack_space - 1;
  1855.      code_attribute.opcode_getfield(idx,Result);
  1856.       end;
  1857.  
  1858. feature {RUN_FEATURE}
  1859.  
  1860.    add_rf(rf: RUN_FEATURE; key: STRING) is
  1861.       require
  1862.      not feature_dictionary.has(key)
  1863.       do
  1864.      feature_dictionary.put(rf,key);
  1865.       end;
  1866.    
  1867. invariant
  1868.    
  1869.    current_type.run_type = current_type;
  1870.    
  1871. end -- RUN_CLASS
  1872.  
  1873.